﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;//
using Newtonsoft.Json;//

namespace Tinygrass.Util.Common
{
    /// <summary>
    /// Marlon 2019-1-18
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class TreeHelper<T>
    {
        TreeNode<T> _RootNode;
        List<TreeNode<T>> NodeList;
        public TreeNode<T> GetRootNode { get { return _RootNode; } }

        public TreeHelper()
        {
            _RootNode = new TreeNode<T>();
            NodeList = new List<TreeNode<T>>();
        }
        public TreeHelper(List<T> lsModel, string idFieldName = "ID", string pidFieldName = "ParentID", string nameFieldName = "Name")
        {
            _RootNode = new TreeNode<T>();
            NodeList = new List<TreeNode<T>>();

            RenderTree(lsModel, idFieldName, pidFieldName, nameFieldName);
        }


        public void RenderTree(List<T> lsModel, string idFieldName = "ID", string pidFieldName = "ParentID", string nameFieldName = "Name")
        {
            Type t = typeof(T);
            var props = t.GetProperties();
            PropertyInfo propID = null, propPID = null, propName = null;

            #region 判断三个字段是否存在
            bool isIdFieldExist = false, isPIdFieldExist = false, isNameFieldExist = false;
            foreach (var prop in props)
            {
                if (prop.Name == idFieldName)
                {
                    propID = prop;
                    isIdFieldExist = true;
                }
                else if (prop.Name == pidFieldName)
                {
                    propPID = prop;
                    isPIdFieldExist = true;
                }
                else if (prop.Name == nameFieldName)
                {
                    propName = prop;
                    isNameFieldExist = true;
                }
                if (isIdFieldExist && isPIdFieldExist && isNameFieldExist)
                { break; }
            }
            if (!isIdFieldExist && !isPIdFieldExist)
            {
                return;
            }
            if (!isNameFieldExist)
            {
                nameFieldName = idFieldName;
                propName = propID;
            }
            #endregion

            #region 转化成节点列表
            NodeList = new List<TreeNode<T>>();
            foreach (var model in lsModel)
            {
                try
                {
                    var oID = propID.GetValue(model, null);
                    var oPID = propPID.GetValue(model, null);
                    var oName = propName.GetValue(model, null);
                    if (oID == null || oPID == null)
                    { continue; }
                    var strID = Convert.ToString(oID);
                    var strPID = Convert.ToString(oPID);
                    if (oName == null)
                    { oName = oID; }
                    var strName = Convert.ToString(oName);

                    var node = new TreeNode<T>();
                    node.NodeID = strID;
                    node.NodeName = strName;
                    node.NodeObject = model;
                    node.ParentID = strPID;
                    node.ChildrenNodes = new List<TreeNode<T>>();
                    NodeList.Add(node);
                }
                catch { continue; }
            }
            #endregion

            #region 渲染树

            // 寻找根结点 
            foreach (var nd in NodeList)
            {
                if (!NodeList.Exists(a => a.NodeID == nd.ParentID))
                {
                    _RootNode = nd;
                    break;
                }
            }
            if (_RootNode == null)
            { return; }
            //
            _RootNode.IsRendered = true;
            _RootNode.Deepth = 0;
            _RootNode.ParentID = "";
            _RootNode.ParentNode = null;
            ResolveChildrenNodes(_RootNode);
            #endregion
        }

        protected void ResolveChildrenNodes(TreeNode<T> nd)
        {
            var ls = NodeList.Where(a => a.ParentID == nd.NodeID).ToList();
            if (ls != null && ls.Count > 0)
            {
                for (var i = 0; i < ls.Count; i++)
                {
                    var cnd = ls[i];
                    if (!cnd.IsRendered)//防止死循环（渲染过一次的不再渲染）
                    {
                        cnd.IsRendered = true;
                        cnd.Deepth = nd.Deepth + 1;
                        cnd.ParentNode = nd;
                        nd.ChildrenNodes.Add(cnd);

                        ResolveChildrenNodes(cnd);
                    }
                }
            }

        }

    }

    public class TreesHelper<T>
    {
        List<TreeNode<T>> _RootNodeList;
        List<TreeNode<T>> NodeList;
        public List<TreeNode<T>> GetRootNodeList { get { return _RootNodeList; } }
        public TreesHelper()
        {

            _RootNodeList = new List<TreeNode<T>>();
            NodeList = new List<TreeNode<T>>();
        }
        public TreesHelper(List<T> lsModel, string idFieldName = "ID", string pidFieldName = "ParentID", string nameFieldName = "Name", string nodesName = "")
        {

            _RootNodeList = new List<TreeNode<T>>();
            NodeList = new List<TreeNode<T>>();

            RenderTree(lsModel, idFieldName, pidFieldName, nameFieldName, nodesName);
        }


        public void RenderTree(List<T> lsModel, string idFieldName = "ID", string pidFieldName = "ParentID", string nameFieldName = "Name", string nodesName = "")
        {
            if (nodesName != "") { SetNodesName(nodesName); }//

            Type t = typeof(T);
            var props = t.GetProperties();
            PropertyInfo propID = null, propPID = null, propName = null;

            #region 判断三个字段是否存在
            bool isIdFieldExist = false, isPIdFieldExist = false, isNameFieldExist = false;
            foreach (var prop in props)
            {
                if (prop.Name == idFieldName)
                {
                    propID = prop;
                    isIdFieldExist = true;
                }
                else if (prop.Name == pidFieldName)
                {
                    propPID = prop;
                    isPIdFieldExist = true;
                }
                else if (prop.Name == nameFieldName)
                {
                    propName = prop;
                    isNameFieldExist = true;
                }
                if (isIdFieldExist && isPIdFieldExist && isNameFieldExist)
                { break; }
            }
            if (!isIdFieldExist && !isPIdFieldExist)
            {
                return;
            }
            if (!isNameFieldExist)
            {
                nameFieldName = idFieldName;
                propName = propID;
            }
            #endregion

            #region 转化成节点列表
            NodeList = new List<TreeNode<T>>();
            foreach (var model in lsModel)
            {
                try
                {
                    var oID = propID.GetValue(model, null);
                    var oPID = propPID.GetValue(model, null);
                    var oName = propName.GetValue(model, null);
                    if (oID == null || oPID == null)
                    { continue; }
                    var strID = Convert.ToString(oID);
                    var strPID = Convert.ToString(oPID);
                    if (oName == null)
                    { oName = oID; }
                    var strName = Convert.ToString(oName);

                    var node = new TreeNode<T>();
                    node.NodeID = strID;
                    node.NodeName = strName;
                    node.NodeObject = model;
                    node.ParentID = strPID;
                    node.ChildrenNodes = new List<TreeNode<T>>();
                    NodeList.Add(node);
                }
                catch { continue; }
            }
            #endregion

            #region 渲染树

            // 寻找根结点 
            foreach (var nd in NodeList)
            {
                if (!NodeList.Exists(a => a.NodeID == nd.ParentID))
                {
                    _RootNodeList.Add(nd);
                    // break;
                }
            }
            if (_RootNodeList.Count == 0)
            { return; }
            //

            foreach (var _RootNode in _RootNodeList)
            {
                _RootNode.IsRendered = true;
                _RootNode.Deepth = 0;
                _RootNode.ParentID = "";
                _RootNode.ParentNode = null;
                ResolveChildrenNodes(_RootNode);
            }

            #endregion
        }
        /// <summary>
        /// 此方法 无用
        /// </summary>
        /// <param name="nodesName"></param>
        void SetNodesName(string nodesName)
        {
            var type = typeof(TreeNode<T>);
            var prop = type.GetProperty("ChildrenNodes");
            if (prop != null)
            {
                var jsonProp = prop.GetCustomAttribute(typeof(JsonPropertyAttribute));
                if (jsonProp != null)
                {
                    var jsonProp2 = jsonProp as JsonPropertyAttribute;
                    jsonProp2.PropertyName = nodesName;
                }
            }

        }

        protected void ResolveChildrenNodes(TreeNode<T> nd)
        {
            var ls = NodeList.Where(a => a.ParentID == nd.NodeID).ToList();
            if (ls != null && ls.Count > 0)
            {
                for (var i = 0; i < ls.Count; i++)
                {
                    var cnd = ls[i];
                    if (!cnd.IsRendered)//防止死循环（渲染过一次的不再渲染）
                    {
                        cnd.IsRendered = true;
                        cnd.Deepth = nd.Deepth + 1;
                        cnd.ParentNode = nd;
                        nd.ChildrenNodes.Add(cnd);

                        ResolveChildrenNodes(cnd);
                    }
                }
            }

        }
    }

    public class TreeNode<T>
    {
        [JsonProperty(PropertyName = "id")]
        public string NodeID { get; set; }
        [JsonProperty(PropertyName = "text")]
        public string NodeName { get; set; }
        public T NodeObject { get; set; }

        [JsonProperty(PropertyName = "parentId")]
        public string ParentID { get; set; }
        //public string ParentName { get; set; }
        //public T ParentObject { get; set; }
        [JsonIgnore]
        public TreeNode<T> ParentNode { get; set; }

        [JsonProperty(PropertyName = "children")]
        public List<TreeNode<T>> ChildrenNodes { get; set; }


        public int Deepth { get; set; }

        //防止死循环（渲染过一次的不再渲染）
        public bool IsRendered { get; set; }
    }
}
